home *** CD-ROM | disk | FTP | other *** search
/ Aminet 33 / Aminet 33 - October 1999.iso / Aminet / dev / src / WBBump_src.lha / WBBump_src / Plugins / clock.wbbplugin.e < prev    next >
Encoding:
Text File  |  1999-06-30  |  10.0 KB  |  549 lines

  1. /* **************** */
  2. /* clock.wbbplugin.e */
  3. /* **************** */
  4.  
  5.  
  6.  
  7. /*
  8.     WBBump - Bumpmapping on the Workbench!
  9.  
  10.     Copyright (C) 1999  Thomas Jensen - dm98411@edb.tietgen.dk
  11.  
  12.     This program is free software; you can redistribute it and/or modify
  13.     it under the terms of the GNU General Public License as published by
  14.     the Free Software Foundation; either version 2 of the License, or
  15.     (at your option) any later version.
  16.  
  17.     This program is distributed in the hope that it will be useful,
  18.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  19.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  20.     GNU General Public License for more details.
  21.  
  22.     You should have received a copy of the GNU General Public License
  23.     along with this program; if not, write to the Free Software Foundation,
  24.     Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  25. */
  26.  
  27.  
  28.  
  29. /*
  30. */
  31.  
  32. OPT PREPROCESS
  33.  
  34.  
  35.  
  36. LIBRARY 'clock.wbbplugin', 1, 0, 'clock.wbbplugin 1.0 (7/5/99)' IS
  37.     pluginInit(A0), pluginCleanup(),
  38.     pluginInitInstance(A0), pluginFreeInstance(A0),
  39.     pluginGetAttr(D1,D2,A0), pluginSetAttr(D1,D2,D3),
  40.     pluginDoAction(A0,A1,A2,A3)
  41.  
  42.  
  43.  
  44.  
  45.  
  46. /* just to put flags in top of source */
  47.  
  48. #define    ARGTEMPLATE      'SIT/S,CET_OFFSET/N,SUMMERTIME/S'
  49. #define    PLUGINTYPE      PLUGINTYPE_BUMPER
  50. CONST    ISMODIFIER    = FALSE                -> this is not a modifying plugin
  51. CONST    ISSTATIC    = FALSE                -> this is not a static plugin (see plugin.e)
  52.  
  53.  
  54. /* needed modules */
  55.  
  56.  
  57.  
  58. MODULE    'utility',
  59.         'utility/tagitem',
  60.  
  61.         'datatypes',
  62.  
  63.         'dos/dos'
  64.  
  65.  
  66. MODULE    '*/plugin_const',
  67.         '*/errors',
  68.         '*/chunkyimage',
  69.         '*/argparser'
  70.  
  71.  
  72. /* time modes */
  73. ENUM    MODE_NORMAL,
  74.         MODE_SIT
  75.  
  76.  
  77.  
  78. OBJECT handle
  79.     width        :    LONG
  80.     height        :    LONG
  81.     args        :    PTR TO CHAR
  82.     rdargs        :    LONG
  83.     mode        :    LONG        -> MODE_xxx
  84.     secs        :    LONG        -> secs since midnight
  85.     secs_last    :    LONG        -> last reading
  86.     sit            :    INT            -> SIT ticks
  87.     sit_last    :    INT            -> SIT ticks last time
  88.     offset        :    INT            -> offset in hours from CET
  89.     time[5]        :    ARRAY OF CHAR
  90. ENDOBJECT
  91.  
  92.  
  93. DEF    digits_png_size=1353
  94.  
  95.  
  96. DEF    lasterr=NIL
  97.  
  98.  
  99. /* offsets into image */
  100. DEF    offsets=NIL:PTR TO LONG
  101. /* widths of digits */
  102. DEF    widths=NIL:PTR TO LONG
  103.  
  104. DEF    max_width_num=-1
  105.  
  106.  
  107. /* global image of digits */
  108. DEF    digits=NIL:PTR TO cimg
  109.  
  110.  
  111.  
  112. PROC main()
  113.     /* library init code here */
  114.     /* this is executed in Forbid() so be carefull */
  115.     /* better use pluginInit() for most things */
  116.  
  117.     /* we need utility.library for GetTagData() */
  118.     IF (utilitybase := OpenLibrary('utility.library', 37)) = NIL THEN RETURN FALSE
  119.  
  120.  
  121. ENDPROC
  122.  
  123.  
  124.  
  125. PROC close()
  126.     /* free stuff allocated in main() here */
  127.  
  128.     IF utilitybase THEN CloseLibrary(utilitybase)
  129.  
  130. ENDPROC
  131.  
  132.  
  133.  
  134.  
  135. /* init the "class" */
  136.  
  137. PROC pluginInit(tags:PTR TO tagitem)
  138.     /* do initializations that can't be done in main() here */
  139.     /* read files, open libs, etc. */
  140.  
  141.     DEF    i
  142.  
  143.     IF (datatypesbase := OpenLibrary('datatypes.library', 39)) = NIL THEN RETURN FALSE
  144.  
  145.  
  146.     offsets    := [0, 35, 68, 104, 137, 173, 207, 244, 277, 312, 347, 365, 414]:LONG
  147.  
  148.     /* calc witdhs */
  149.     widths := New(12*4)
  150.     FOR i := 0 TO 11 DO widths[i] := offsets[i+1] - offsets[i]
  151.  
  152.     /* get max width */
  153.     max_width_num := -1
  154.     FOR i := 0 TO 9
  155.         IF widths[i] > max_width_num THEN max_width_num := widths[i]
  156.     ENDFOR
  157.  
  158. ENDPROC TRUE
  159.  
  160.  
  161.  
  162.  
  163. /* free the "class" */
  164.  
  165. PROC pluginCleanup()
  166.     /* cleanup things done in pluginInit() */
  167.  
  168.     END digits
  169.  
  170.     IF datatypesbase THEN CloseLibrary(datatypesbase)
  171.  
  172. ENDPROC
  173.  
  174.  
  175.  
  176.  
  177.  
  178.  
  179.  
  180.  
  181.  
  182. /* init an instance */
  183.  
  184. PROC pluginInitInstance(tags:PTR TO tagitem) HANDLE
  185.     DEF    h=NIL:PTR TO handle,
  186.         args=NIL:PTR TO LONG,
  187.         width, height
  188.  
  189.     /* this function is allways called by WBBump */
  190.     /* use it to allocate buffers, etc */
  191.  
  192.     /* return a handle to an "instance" */
  193.  
  194.  
  195.     IF digits = NIL
  196.         getDigits()
  197.     ENDIF
  198.  
  199.  
  200.     /* alloc handle */
  201.     NEW h
  202.  
  203.  
  204.  
  205.     /* set global vars */
  206.  
  207.     IF tags
  208.         width        := GetTagData(PLUGINTAG_WIDTH, -1, tags)
  209.         height        := GetTagData(PLUGINTAG_HEIGHT, -1, tags)
  210.         h.args        := GetTagData(PLUGINTAG_ARGS, NIL, tags)
  211.         args        := NEW [0, 0, 0, 0]
  212.         IF h.args
  213.             h.rdargs    := parseargs(ARGTEMPLATE, args, h.args)
  214.             IF h.rdargs = NIL THEN eThrow(-1, 'Bad arguments, template is %s', NEW [ARGTEMPLATE])
  215.         ENDIF
  216.         h.mode        := IF args[0] THEN MODE_SIT ELSE MODE_NORMAL
  217.         h.offset    := IF args[1] THEN Long(args[1]) ELSE 0
  218.         IF args[2] THEN h.offset := h.offset - 1
  219.         IF h.offset < 0 THEN h.offset := h.offset + 24
  220.     ELSE
  221.         RETURN NIL
  222.     ENDIF
  223.  
  224.  
  225.  
  226.     /* check size */
  227.     IF    (width <= 0) OR (height <= 0)
  228.         h.width := h.maxwidth() + 10
  229.         h.height := 50 + 10
  230.     ELSE
  231.         IF (width < h.maxwidth()) OR (height < 50) THEN eThrow(-1, 'Initial size too small, Clock plugin needs %ld x %ld in this mode', NEW [h.maxwidth(), 50])
  232.         h.width := width
  233.         h.height := height
  234.     ENDIF
  235.  
  236.     /* return NIL if there was an error */
  237.  
  238. EXCEPT DO
  239.     IF exception
  240.         IF h THEN pluginFreeInstance(h)
  241.         lasterr := exceptioninfo
  242.         RETURN NIL
  243.     ENDIF
  244. ENDPROC h
  245.  
  246.  
  247.  
  248.  
  249. /* load image */
  250. PROC getDigits() HANDLE
  251.     DEF    fh=NIL,
  252.         fname[256]:STRING
  253.  
  254.  
  255.     StringF(fname, 'T:WBB.clock.temp.png.\z\h[8]', FindTask(0))
  256.  
  257.     IF (fh := Open(fname, MODE_NEWFILE)) = NIL THEN eThrow(-1, 'Unable to create temp image in T:')
  258.  
  259.     IF Write(fh, {digits_png}, digits_png_size) <> digits_png_size THEN eThrow(-1, 'Write error on file: %s', NEW [fname])
  260.  
  261.     Close(fh); fh := NIL
  262.  
  263.     NEW digits.newfromDT(fname)
  264.  
  265.     DeleteFile(fname)
  266.  
  267. EXCEPT DO
  268.     IF fh THEN Close(fh)
  269.     ReThrow()
  270. ENDPROC TRUE
  271.  
  272.  
  273.  
  274.  
  275. /* free an instance */ 
  276.  
  277. PROC pluginFreeInstance(h:PTR TO handle)
  278.  
  279.     /* cleanup stuff allocated in pluginInitInstance() */
  280.  
  281.     IF h.rdargs THEN freeargs(h.rdargs)
  282.  
  283. ENDPROC
  284.  
  285.  
  286.  
  287. /* get an attribute from the instance, or globally if handle = 0 */
  288.  
  289. PROC pluginGetAttr(h:PTR TO handle, attr, valueptr:PTR TO LONG)
  290.  
  291.     /* this is where WBBump gets information from the plugin */
  292.     /* look in plugin.e to see what is required */
  293.  
  294.     IF h
  295.         SELECT attr
  296.  
  297.         CASE PLUGINTAG_WIDTH
  298.             valueptr[0] := h.width    -> return the width
  299.             RETURN TRUE
  300.  
  301.         CASE PLUGINTAG_HEIGHT
  302.             valueptr[0] := h.height    -> return the height
  303.             RETURN TRUE
  304.  
  305.         CASE PLUGINTAG_NEEDUPDATE
  306.             valueptr[0] := h.needupdate()
  307.             RETURN TRUE
  308.  
  309.         ENDSELECT
  310.     ENDIF
  311.  
  312.     SELECT attr
  313.  
  314.     CASE PLUGINTAG_WIDTH
  315.         valueptr[0] := -1
  316.         RETURN TRUE
  317.  
  318.     CASE PLUGINTAG_HEIGHT
  319.         valueptr[0] := -1
  320.         RETURN TRUE
  321.  
  322.     CASE PLUGINTAG_ISMODIFIER
  323.         valueptr[0] := ISMODIFIER    -> see top of file
  324.         RETURN TRUE
  325.  
  326.     CASE PLUGINTAG_COMMANDNAME
  327.         valueptr[0] := 'PLUGIN_CLOCK'    -> tooltypes command
  328.         RETURN TRUE
  329.  
  330.     CASE PLUGINTAG_ISSTATIC
  331.         valueptr[0] := ISSTATIC        -> see top of file
  332.         RETURN TRUE
  333.  
  334.     CASE PLUGINTAG_TYPE
  335.         valueptr[0] := PLUGINTYPE
  336.         RETURN TRUE
  337.  
  338.     CASE PLUGINTAG_NAME
  339.         valueptr[0] := 'clock.wbbplugin'
  340.         RETURN TRUE
  341.  
  342.     CASE PLUGINTAG_COPYRIGHT
  343.         valueptr[0] := '©1999 Thomas Jensen - dm98411@edb.tietgen.dk'
  344.         RETURN TRUE
  345.  
  346.     CASE PLUGINTAG_AUTHOR
  347.         valueptr[0] := 'Thomas Jensen - dm98411@edb.tietgen.dk'
  348.         RETURN TRUE
  349.  
  350.     CASE PLUGINTAG_DESC
  351.         valueptr[0] := 'Shows clock as bumpmap\nKnows "normal" clock and Internet time'
  352.         RETURN TRUE
  353.  
  354.     CASE PLUGINTAG_LASTERROR
  355.         valueptr[0] := lasterr
  356.         RETURN TRUE
  357.  
  358.     DEFAULT
  359.         lasterr := 'Unknown tag'
  360.         RETURN FALSE            -> return false if the tag is unknown
  361.  
  362.     ENDSELECT
  363.  
  364. ENDPROC FALSE
  365.  
  366.  
  367.  
  368. PROC pluginSetAttr(h:PTR TO handle, attr, value)
  369.  
  370.     /* later this may be used to set plugin attributes */
  371.     /* if there's no attributes to set, return FALSE */
  372.  
  373. ENDPROC FALSE
  374.  
  375.  
  376.  
  377.  
  378. PROC pluginDoAction(h:PTR TO handle, inbuf:PTR TO CHAR, outbuf:PTR TO CHAR, tags:PTR TO tagitem) HANDLE
  379.  
  380.     /* this is the "action" part of the plugin */
  381.     /* it is called each time the plugin's services are needed */
  382.     /* if the plugin says TRUE to ISMODIFIER then inbuf MAY contain an image */
  383.     /* othervise it a NIL pointer */
  384.     /* tags is currently not used */
  385.  
  386.  
  387.     h.updatetime()
  388.  
  389.     h.drawdigits(outbuf)
  390.  
  391. EXCEPT DO
  392.     /* return FALSE if something went wrong */
  393.     IF exception
  394.         lasterr := exceptioninfo
  395.         RETURN FALSE
  396.     ENDIF
  397. ENDPROC TRUE
  398.  
  399.  
  400.  
  401.  
  402. /* handle methods */
  403.  
  404. PROC updatetime() OF handle HANDLE
  405.     DEF    ds:PTR TO datestamp,
  406.         sit_secs,
  407.         h,m,s
  408.  
  409.     NEW ds
  410.  
  411.     DateStamp(ds)
  412.  
  413.     self.secs := (ds.minute * 60) + (ds.tick / 50)
  414.  
  415.     h := Div(self.secs, 60*60)
  416.     m := Div(self.secs, 60) - (h * 60)
  417.     s := self.secs - (h*60*60) - (m*60)
  418.  
  419.     sit_secs := self.secs + (self.offset * 60 * 60)
  420.  
  421.     self.sit := Mod(Div(Mul(sit_secs, 1000), (60*60*24)), 1000)
  422.  
  423.     IF self.mode = MODE_NORMAL
  424.         self.time[0] := h / 10
  425.         self.time[1] := Mod(h, 10)
  426.         self.time[2] := 10                        -> ':'
  427.         self.time[3] := m / 10
  428.         self.time[4] := Mod(m, 10)
  429.     ELSE
  430.         self.time[0] := 11                        -> '@'
  431.         self.time[1] := self.sit / 100
  432.         self.time[2] := Mod(self.sit / 10, 10)
  433.         self.time[3] := Mod(self.sit, 10)
  434.     ENDIF
  435.  
  436. EXCEPT DO
  437.     END ds
  438.     ReThrow()
  439. ENDPROC
  440.  
  441.  
  442.  
  443. PROC needupdate() OF handle
  444.     DEF    mode
  445.  
  446.  
  447.     self.updatetime()
  448.  
  449.     mode := self.mode    
  450.  
  451.     SELECT mode
  452.     CASE MODE_NORMAL
  453.         RETURN IF Div(self.secs_last, 60) = Div(self.secs, 60) THEN FALSE ELSE TRUE
  454.     CASE MODE_SIT
  455.         RETURN IF self.sit = self.sit_last THEN FALSE ELSE TRUE
  456.     ENDSELECT
  457.  
  458. ENDPROC FALSE
  459.  
  460.  
  461. PROC maxwidth() OF handle
  462.     DEF    mode
  463.  
  464.     mode := self.mode
  465.  
  466.     SELECT mode
  467.     CASE MODE_NORMAL
  468.         RETURN  (max_width_num * 4) + widths[10] /* : */
  469.     CASE MODE_SIT
  470.         RETURN (max_width_num * 3) + widths[11] /* @ */
  471.     ENDSELECT
  472.  
  473. ENDPROC
  474.  
  475.  
  476. PROC curwidth() OF handle
  477.     DEF    mode
  478.  
  479.     mode := self.mode
  480.  
  481.     SELECT mode
  482.     CASE MODE_NORMAL
  483.         RETURN  widths[self.time[0]] + widths[self.time[1]] + widths[self.time[2]] + widths[self.time[3]] + widths[self.time[4]]
  484.     CASE MODE_SIT
  485.         RETURN widths[self.time[0]] + widths[self.time[1]] + widths[self.time[2]] + widths[self.time[3]]
  486.     ENDSELECT
  487.  
  488. ENDPROC
  489.  
  490.  
  491.  
  492. PROC drawdigit(dignum, x, y, buf, width) OF handle HANDLE
  493.     DEF    ix, iy,
  494.         index,
  495.         digbuf=NIL
  496.  
  497.     IF digits.lock(NEW [CIMGTAG_LOCK_BUF, {digbuf}, 0]) = FALSE THEN eThrow(-1, 'Internal error in digits.lock()')
  498.  
  499.     index := x + (y * width)
  500.     FOR iy := 0 TO 49
  501.         FOR ix := 0 TO widths[dignum]-1
  502.             buf[index + ix + (iy * width)] := digbuf[offsets[dignum] + ix + (iy * digits.width)]
  503.         ENDFOR
  504.     ENDFOR
  505.  
  506. EXCEPT DO
  507.     digits.unlock()
  508.     ReThrow()
  509. ENDPROC
  510.  
  511.  
  512. PROC drawdigits(buf) OF handle
  513.     DEF    i,
  514.         num,
  515.         curx,
  516.         offx, offy
  517.  
  518.  
  519.     self.secs_last := self.secs
  520.     self.sit_last := self.sit
  521.  
  522.  
  523.     IF self.mode = MODE_NORMAL THEN num := 5 ELSE num := 4
  524.  
  525.     offx := (self.width - self.curwidth()) / 2
  526.     offy := (self.height - 50) / 2
  527.  
  528.     curx := offx
  529.  
  530.     FOR i := 0 TO num-1
  531.         self.drawdigit(self.time[i], curx, offy, buf, self.width)
  532.         curx := curx + widths[self.time[i]]
  533.     ENDFOR
  534. ENDPROC
  535.  
  536.  
  537.  
  538.  
  539.  
  540.  
  541. digits_png:
  542.     INCBIN    'Clock.png'
  543. digits_png_end:
  544.  
  545.  
  546.  
  547.  
  548.  
  549.